using System;
using System.Data;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using MySql.Data.MySqlClient;

namespace TestGUI
{
	/// <summary>
	/// This class is the main backbone of this application. It manages all of the Database connections, as well as
	/// the current logged in user. It facilitates communications between all parts of the program, and is any window's link
	/// to the database. Only one session object ever exists, and it is created right at program launch by LoginWindow.
	/// </summary>
	public class Session
	{
		/*Global variables*/
		MySqlConnection conn;
		MySqlCommand cmd;
		Employee employee;
		Manager manager, tempManager;
		string adminPass, empsPerShift;

		/*Constructor*/
		public Session()
		{
			OpenConnection();
		}


		/*Destructor*/
		~Session() 
		{
			CloseConnection();
		}
	

		/*MySql Connection Functions*/

		//Opens the server connection, and loads data from the administrator table for the admin account and employeesPerShift.
		public void OpenConnection()
		{
			try 
			{
				string connStr = String.Format("server={0};uid={1};pwd={2};database={3}","localhost", "root", "qwpoas", "Jessica");
				conn = new MySqlConnection(connStr);
				conn.Open();
				string sql = "SELECT * FROM administrator;";
				cmd = new MySqlCommand(sql, conn);
				MySqlDataReader rdr = cmd.ExecuteReader();
				if (!rdr.Read()) 
				{
					rdr.Close();
					return;
				}
				Object[] o = new Object[2];
				rdr.GetValues(o);
				rdr.Close();
				adminPass = o[0].ToString();
				empsPerShift = o[1].ToString();
			} 
			catch (Exception e) 
			{
				if (MessageBox.Show("Unable to initiate connection. Please make sure your database has been properly configured. Would you like to view more detailed information?","Error.",System.Windows.Forms.MessageBoxButtons.YesNo) == System.Windows.Forms.DialogResult.Yes) 
				{
					MessageBox.Show(e.ToString());
				}
				return;
			}
		}

		//Closes the connection.
		public void CloseConnection() 
		{
			conn.Close();
		}

		/*Variable Reporting Functions*/

		//Returns the current admin account password (NOT MD5'ed).
		public string getAdminPass() 
		{
			return adminPass;
		}
		
		//Returns the current number of employees per shift.
		public string getEmployeesPerShift() 
		{
			return empsPerShift;
		}

		//Returns the manager being currently editted by the admin.
		public Manager getTempManager() 
		{
			return tempManager;
		}

		//Returns either the current logged in employee, or the employee being editted by the current logged in manager.
		public Employee getEmployee() 
		{
			return employee;
		}

		//Returns the current logged in manager.
		public Manager getManager() 
		{
			return manager;
		}


		/*Session Management*/

		//Check whether or not a certain login is valid admin criteria.
		public bool checkAdmin(string name, string pass) 
		{
			if (name.Equals("admin") && pass.Equals(adminPass)) 
			{
				return true;
			} 
			else if (name.Equals("admin")) 
			{
				MessageBox.Show("Please enter a valid password for the Administrator account.");
			}
			return false;
		}


		//Attempt to login with the specified username, password, and managerial status.
		public bool login(string name, string pass, bool man) 
		{
			try 
			{
				//Make sure to turn the password into an MD5 hash, since that's the way it's stored in the database.
				pass = MD5(pass);

				if (man) //This will be true if the manager radio button was selected.
				{
					string sql = "SELECT * FROM managers WHERE username=\""+name+"\" && password=\""+pass+"\";";
					cmd = new MySqlCommand(sql, conn);
					MySqlDataReader rdr = cmd.ExecuteReader();
					if (!rdr.Read()) 
					{
						rdr.Close();
						sql = "SELECT * FROM managers WHERE username=\""+name+"\";";
						cmd = new MySqlCommand(sql, conn);
						rdr = cmd.ExecuteReader();
						if (!rdr.Read()) 
						{
							MessageBox.Show("No such manager exists.");
						} 
						else 
						{
							MessageBox.Show("Incorrect password.");
						}
						rdr.Close();
						return false;
					}
					//If the previous was false, then the manager does exist, so proceed to log him/her in.
					//
					//Note: The login process consists of setting either the manager or the employee variable
					//      (both previously null) to a corresponding object that represents that particular user, 
					//		created on the fly with data drawn from the database.
					Object[] o = new Object[3];
					rdr.GetValues(o);
					manager = new Manager((o[0].ToString()), (o[1].ToString()), (o[2].ToString()));
					rdr.Close();
					return true;
				} 
				else //This will be reached if the employee radio button was selected.
				{
					string sql = "SELECT * FROM employees WHERE username=\""+name+"\" && password=\""+pass+"\";";
					cmd = new MySqlCommand(sql, conn);
					MySqlDataReader rdr = cmd.ExecuteReader();
					if (!rdr.Read()) 
					{
						rdr.Close();
						sql = "SELECT * FROM employees WHERE username=\""+name+"\";";
						cmd = new MySqlCommand(sql, conn);
						rdr = cmd.ExecuteReader();
						if (!rdr.Read()) 
						{
							MessageBox.Show("No such employee exists.");
						} 
						else 
						{
							MessageBox.Show("Incorrect password.");
						}
						rdr.Close();
						return false;
					}
					//If the previous was false, then the employee does exist, so proceed to log him/her in.
					Object[] o = new Object[7];
					rdr.GetValues(o);
					employee = new Employee((o[0].ToString()), (o[1].ToString()), (o[2].ToString()), (o[3].ToString()), (o[4].ToString()), (o[5].ToString()), (o[6].ToString()));
					rdr.Close();
					return true;
				}
					
			} 
			catch (Exception e) 
			{
				if (MessageBox.Show("Login process could not be completed. Would you like to view more detailed information?","Error.",System.Windows.Forms.MessageBoxButtons.YesNo) == System.Windows.Forms.DialogResult.Yes) 
				{
					MessageBox.Show(e.ToString());
				}
				return false;
			}
		}


		//Clear out the session.
		public void logout() 
		{
			employee = null;
			manager = null;
		}


		/*Database Read & Write*/

		//Reset all data in the databases to their default (and empty) values.
		public void clearAllData() 
		{
			try 
			{
				//First, delete all the "days" tables from the database. Each of these tables 
				//represents the list of days off one employee has requested.
				ArrayList tablesForDeleting = new ArrayList();
				//Search for all tables in the database.
				string sql = "SHOW TABLES;";
				string tableName;
				cmd = new MySqlCommand(sql, conn);
				MySqlDataReader rdr = cmd.ExecuteReader();
				while (rdr.Read()) 
				{
					Object[] o = new Object[1];
					rdr.GetValues(o);
					tablesForDeleting.Add(o[0].ToString());
				}
				rdr.Close();
				//Go through the list, and drop the "days" tables.
				for (int i = 0; i < tablesForDeleting.Count; i++) 
				{
					tableName = tablesForDeleting[i].ToString();
					if (tableName.StartsWith("days")) 
					{
						sql = "DROP TABLE "+tableName+";";
						cmd = new MySqlCommand(sql, conn);
						cmd.ExecuteNonQuery();
					}
				}
				//Now, empty the schedule, manager, and employee tables.
				sql = "DELETE FROM managers;";
				cmd = new MySqlCommand(sql, conn);
				cmd.ExecuteNonQuery();
				sql = "DELETE FROM employees;";
				cmd = new MySqlCommand(sql, conn);
				cmd.ExecuteNonQuery();
				sql = "DELETE FROM schedule;";
				cmd = new MySqlCommand(sql, conn);
				cmd.ExecuteNonQuery();
			} 
			catch (Exception e) 
			{
				if (MessageBox.Show("Could not clear the database. Would you like to view more detailed information?","Error.",System.Windows.Forms.MessageBoxButtons.YesNo) == System.Windows.Forms.DialogResult.Yes) 
				{
					MessageBox.Show(e.ToString());
				}
			}
		}


		//Specify the number of employees that should work in any given shift.
		public bool setEmployeesPerShift(int emps) 
		{
			//Change the local variable, and then commit it to the administrator table in the database.
			empsPerShift = ""+emps;
			string sql = "UPDATE administrator set employees_per_shift="+empsPerShift+";";
			cmd = new MySqlCommand(sql, conn);
			try 
			{
				cmd.ExecuteNonQuery();
				return true;
			}
			catch (Exception e) 
			{
				if (MessageBox.Show("An unexpected error occured while setting this global preference. Would you like to view more detailed information?","Error.",System.Windows.Forms.MessageBoxButtons.YesNo) == System.Windows.Forms.DialogResult.Yes) 
				{
					MessageBox.Show(e.ToString());
				}
			}
			return false;
		}
			

		//Set the password for the admin account.
		public bool setAdminPass(string pass) 
		{
			//Make sure the password is valid, and then update the database entry.
			if (pass.Length < 6 || pass.Length > 10) 
			{
				MessageBox.Show("Password must be between 6 and 10 characters.");
				return false;
			}
			adminPass = pass;
			string sql = "UPDATE administrator set password=\""+adminPass+"\";";
			cmd = new MySqlCommand(sql, conn);
			try 
			{
				cmd.ExecuteNonQuery();
				return true;
			}
			catch (Exception e) 
			{
				if (MessageBox.Show("An error occured while attempting to change the admin password. Would you like to view more detailed information?","Error.",System.Windows.Forms.MessageBoxButtons.YesNo) == System.Windows.Forms.DialogResult.Yes) 
				{
					MessageBox.Show(e.ToString());
				}
			}
			return false;
		}


		//Change the password of either an employee or manager, as well as set whether an employee is full- or part-time.
		public bool changePassword(string oldPass, string newPass) 
		{
			//First, MD5 hash the passwords, as always.
			newPass = MD5(newPass);

			//The following if/else jungle determines whether it's changing the password of a selected employee
			//(invoked by a manager), the current employee, and manager logged in.
			if (tempManager != null) 
			{
				//An admin has selected a manager from the List to change the password of.
				tempManager.setPassword(newPass);
				update();
				return true;
			} 
			else if (manager != null && employee != null) 
			{
				//We're dealing with a manager editting an employee. That means, the oldPass string represents their partTime status.
				if (oldPass[0] == 'A') 
				{
					//This means we're only editting the Part Time thing, not the password.
					oldPass = oldPass.Substring(1,oldPass.Length-1);
					employee.setPartTime(oldPass);
				} 
				else 
				{
					employee.setPartTime(oldPass);
					employee.setPassword(newPass);
				}
				update();
				return true;
			} 
			else if (manager != null) 
			{
				//This is reached when a manager is trying to change their own password.
				oldPass = MD5(oldPass);
				if (oldPass.Equals(manager.getPassword())) 
				{
					//The password was correct. So, change the password, then run an update.
					manager.setPassword(newPass);
					update();
					return true;
				} 
				else 
				{
					MessageBox.Show("Current password is not correct.");
					return false;
				}
			} 
			else if (employee != null) 
			{
				//This is reached when an employee is trying to change their own password.
				oldPass = MD5(oldPass);
				if (oldPass.Equals(employee.getPassword())) 
				{
					//The password was correct. So, change the password, then run an update.
					employee.setPassword(newPass);
					update();
					return true;
				} 
				else 
				{
					MessageBox.Show("Current password is not correct.");
				}
			}
			return false;
		}


		//Retrieve a string array of employee names to display in a list format.
		public string[] getEmployeeList() 
		{
			try 
			{
				//First, we need to get an ArrayList (non-static size) of employee objects from the database.
				ArrayList employs = new ArrayList();
				Object[] values;
				string[] emps;
				values = new Object[1];
				string sql = "SELECT username FROM employees;";
				cmd = new MySqlCommand(sql, conn);
				MySqlDataReader rdr = cmd.ExecuteReader();
				while (rdr.Read()) 
				{
					rdr.GetValues(values);
					employs.Add(values[0]);
				}
				rdr.Close();
				//Now, turn that ArrayList into an array.
				if (employs.Count < 1) 
				{
					return null;
				}
				emps = new string[employs.Count];
				for (int i = 0; i < employs.Count; i++) 
				{
					emps[i] = employs[i].ToString();
				}
				return emps;
			}
			catch (Exception e) 
			{
				if (MessageBox.Show("Unexpected error when extracting employee listings. Would you like to view more detailed information?","Error.",System.Windows.Forms.MessageBoxButtons.YesNo) == System.Windows.Forms.DialogResult.Yes) 
				{
					MessageBox.Show(e.ToString());
				}
			}
			return null;
		}


		//Retrieve a string array of manager names to display in a list format.
		public string[] getManagerList() 
		{
			try 
			{
				//First, we need to get an ArrayList (non-static size) of manager objects from the database.
				ArrayList manags = new ArrayList();
				Object[] values;
				string[] mans;
				values = new Object[1];
				string sql = "SELECT username FROM managers;";
				cmd = new MySqlCommand(sql, conn);
				MySqlDataReader rdr = cmd.ExecuteReader();
				while (rdr.Read()) 
				{
					rdr.GetValues(values);
					manags.Add(values[0]);
				}
				rdr.Close();
				if (manags.Count < 1) 
				{
					return null;
				}
				//Now, turn that ArrayList into an actual array.
				mans = new string[manags.Count];
				for (int i = 0; i < manags.Count; i++) 
				{
					mans[i] = manags[i].ToString();
				}
				return mans;
			}
			catch (Exception e) 
			{
				
				if (MessageBox.Show("Unexpected error when extracting manager listings. Would you like to view more detailed information?","Error.",System.Windows.Forms.MessageBoxButtons.YesNo) == System.Windows.Forms.DialogResult.Yes) 
				{
					MessageBox.Show(e.ToString());
				}
			}
			return null;
		}


		//Get an arraylist of the days a specific employee (specified by their userid) has requested.
		public ArrayList getDaysOff(string uid) 
		{
			ArrayList items = new ArrayList();
			string sql = "SELECT * FROM days"+uid+";";
			cmd = new MySqlCommand(sql, conn);
			try 
			{
				MySqlDataReader rdr = cmd.ExecuteReader();
				while (rdr.Read()) 
				{
					Object[] o = new Object[1];
					rdr.GetValues(o);
					items.Add(o[0].ToString());
				}
				rdr.Close();
				return items;
			} 
			catch (Exception e) 
			{
				if (MessageBox.Show("Unexpected error days off table. Would you like to view more detailed information?","Error.",System.Windows.Forms.MessageBoxButtons.YesNo) == System.Windows.Forms.DialogResult.Yes) 
				{
					MessageBox.Show(e.ToString());
				}
				return null;
			}
		}

		
		//Get an employee array of all employee objects.
		public Employee[] getAllEmployees()
		{
			try
			{
				//Create an ArrayList, so that we can have a dynamically sized structure for the indeterminate number of employees.
				ArrayList employs = new ArrayList();
				string sql = "SELECT * FROM employees;";
				cmd = new MySqlCommand(sql, conn);
				MySqlDataReader rdr = cmd.ExecuteReader();
				while (rdr.Read()) 
				{
					Object[] o = new Object[7];
					rdr.GetValues(o);
					Employee newEmp=new Employee((o[0].ToString()), (o[1].ToString()), (o[2].ToString()), (o[3].ToString()), (o[4].ToString()), (o[5].ToString()), (o[6].ToString()));
					//set Total Availibility, aka pickiness factor
					string avail=newEmp.getAvailability();
					int count=0;
					for(int i=0;i<14;i++)
					{
						if(avail[i]=='1')
							count++;
					}
					newEmp.setTotalAvailability(count);
					employs.Add(newEmp);
				}
				rdr.Close();
				
				//NOW, do the thing where we put all the days off in the employee class.
				Employee[] employees = new Employee[employs.Count];
				for (int i = 0; i < employs.Count; i++) 
				{
					employees[i] = (Employee) employs[i];
					ArrayList a = getDaysOff(employees[i].getId());
					if (a != null) 
					{
						DateTime[] daysOff = new DateTime[a.Count];
						for (int j = 0; j < a.Count; j++) 
						{
							daysOff[j] = DateTime.Parse(a[j].ToString());
						}
						employees[i].setDaysOff(daysOff);
					} 
					else 
					{
						employees[i].setDaysOff(null);
					}
				}
				return employees;
			}
			catch(Exception e)
			{
				if (MessageBox.Show("Unexpected error when extracting manager listings. Would you like to view more detailed information?","Error.",System.Windows.Forms.MessageBoxButtons.YesNo) == System.Windows.Forms.DialogResult.Yes) 
				{
					MessageBox.Show(e.ToString());
				}
			}
			return null;
		}
		

		//Write all employee & manager data to the database.
		public void update() 
		{
			if (tempManager != null) 
			{
				//We must be an admin editting a manager. So update the manager.
				string sql = "UPDATE managers SET password=\""+tempManager.getPassword()+"\" WHERE username=\""+tempManager.getName()+"\";";
				cmd = new MySqlCommand(sql, conn);
				try 
				{
					cmd.ExecuteNonQuery();
				} 
				catch (Exception e) 
				{
					if (MessageBox.Show("Error committing changes. Would you like to view more detailed information?","Error.",System.Windows.Forms.MessageBoxButtons.YesNo) == System.Windows.Forms.DialogResult.Yes) 
					{
						MessageBox.Show(e.ToString());
					}
				}
			} 
			else if (manager != null && employee != null) 
			{
				//We must be a manager editting an employee. So update the employee.
				string sql = "UPDATE employees SET password=\""+employee.getPassword()+"\", times="+employee.getTimes()+", shifts="+employee.getShifts()+", availability=\""+employee.getAvailability()+"\", partTime=\""+employee.getPartTime()+"\" WHERE username=\""+employee.getName()+"\";";
				cmd = new MySqlCommand(sql, conn);
				try 
				{
					cmd.ExecuteNonQuery();
				} 
				catch (Exception e) 
				{
					if (MessageBox.Show("Error committing changes. Would you like to view more detailed information?","Error.",System.Windows.Forms.MessageBoxButtons.YesNo) == System.Windows.Forms.DialogResult.Yes) 
					{
						MessageBox.Show(e.ToString());
					}
				}
			} 
			else if (manager != null) 
			{
				string sql = "UPDATE managers SET password=\""+manager.getPassword()+"\" WHERE username=\""+manager.getName()+"\";";
				cmd = new MySqlCommand(sql, conn);
				try 
				{
					cmd.ExecuteNonQuery();
				} 
				catch (Exception e) 
				{
					if (MessageBox.Show("Error committing changes. Would you like to view more detailed information?","Error.",System.Windows.Forms.MessageBoxButtons.YesNo) == System.Windows.Forms.DialogResult.Yes) 
					{
						MessageBox.Show(e.ToString());
					}
				}
			} 
			else if (employee != null) 
			{
				string sql = "UPDATE employees SET password=\""+employee.getPassword()+"\", times="+employee.getTimes()+", shifts="+employee.getShifts()+", availability=\""+employee.getAvailability()+"\" WHERE username=\""+employee.getName()+"\";";
				cmd = new MySqlCommand(sql, conn);
				try 
				{
					cmd.ExecuteNonQuery();
				} 
				catch (Exception e) 
				{
					if (MessageBox.Show("Error committing changes. Would you like to view more detailed information?","Error.",System.Windows.Forms.MessageBoxButtons.YesNo) == System.Windows.Forms.DialogResult.Yes) 
					{
						MessageBox.Show(e.ToString());
					}
				}
			}
		}


		//Add a new employee to the database.
		public bool addEmployeeToDB(string name, string pass, string p) 
		{
			pass = MD5(pass);
			string sql = "INSERT INTO employees (username, times, shifts, availability, password, partTime) VALUES (\""+name+"\", 2, 2, 11111111111111, \""+pass+"\", \""+p+"\");";
			cmd = new MySqlCommand(sql, conn);
			try 
			{
				cmd.ExecuteNonQuery();
				//Before we finish this up, let's create a days table for the employee.
				//First off, find out what the userid for the employee is.
				sql = "SELECT userid FROM employees WHERE username=\""+name+"\";";
				cmd = new MySqlCommand(sql, conn);
				string id = (cmd.ExecuteScalar()).ToString();
				//Next, lets create a table with that id.
				sql = "CREATE TABLE days"+id+" (date VARCHAR(30));";
				cmd = new MySqlCommand(sql, conn);
				cmd.ExecuteNonQuery();
				//Yaydone.
				return true;
			} 
			catch (Exception e) 
			{
				if (MessageBox.Show("Could not add employee. Would you like to view more detailed information?","Error.",System.Windows.Forms.MessageBoxButtons.YesNo) == System.Windows.Forms.DialogResult.Yes) 
				{
					MessageBox.Show(e.ToString());
				}
				return false;
			}
		}

		
		//Add a new manager to the database.
		public bool addManager(string name, string pass) 
		{
			pass = MD5(pass);
			string sql = "INSERT INTO managers (username, password) VALUES (\""+name+"\", \""+pass+"\");";
			cmd = new MySqlCommand(sql, conn);
			try 
			{
				cmd.ExecuteNonQuery();
				return true;
			} 
			catch (Exception e) 
			{
				if (MessageBox.Show("Could not add manager. Would you like to view more detailed information?","Error.",System.Windows.Forms.MessageBoxButtons.YesNo) == System.Windows.Forms.DialogResult.Yes) 
				{
					MessageBox.Show(e.ToString());
				}
				return false;
			}
		}


		//Remove an existing employee from the database.
		public bool removeEmployee(string name) 
		{
			try 
			{
				//First things first; lets grab that userid so we can remove the days table.
				string sql = "SELECT userid FROM employees WHERE username=\""+name+"\";";
				cmd = new MySqlCommand(sql, conn);
				string id = (cmd.ExecuteScalar()).ToString();
				//Now, lets remove that pesky table.
				sql = "DROP TABLE days"+id+";";
				cmd = new MySqlCommand(sql, conn);
				cmd.ExecuteNonQuery();
				//Next up, we need to delete the employee entry from the table.
				sql = "DELETE FROM employees WHERE username=\""+name+"\";";
				cmd = new MySqlCommand(sql, conn);
				cmd.ExecuteNonQuery();
				//Yay.
				return true;
			} 
			catch (Exception e) 
			{
				if (MessageBox.Show("Could not remove employee. Would you like to view more detailed information?","Error.",System.Windows.Forms.MessageBoxButtons.YesNo) == System.Windows.Forms.DialogResult.Yes) 
				{
					MessageBox.Show(e.ToString());
				}
				return false;
			}
		}

		
		//Remove an existing manager from the database.
		public bool removeManager(string name) 
		{
			try 
			{
				//Next up, we need to delete the employee entry from the table.
				string sql = "DELETE FROM managers WHERE username=\""+name+"\";";
				cmd = new MySqlCommand(sql, conn);
				cmd.ExecuteNonQuery();
				//Yay.
				return true;
			} 
			catch (Exception e) 
			{
				if (MessageBox.Show("Could not remove manager. Would you like to view more detailed information?","Error.",System.Windows.Forms.MessageBoxButtons.YesNo) == System.Windows.Forms.DialogResult.Yes) 
				{
					MessageBox.Show(e.ToString());
				}
				return false;
			}
		}


		//Write the schedule to the database.
		public void writeSchedule(string[,] sched) 
		{

			try 
			{
				//First, clear the schedule table
				string sql = "DELETE FROM schedule;";
				cmd = new MySqlCommand(sql, conn);
				cmd.ExecuteNonQuery();
				//Next up, start filling in data.
				for (int i = 0; i < Convert.ToInt32(empsPerShift); i++) 
				{
					sql = "INSERT INTO schedule (sundayam, sundaypm, mondayam, mondaypm, tuesdayam, tuesdaypm, wednesdayam, wednesdaypm, thursdayam, thursdaypm, fridayam, fridaypm, saturdayam, saturdaypm) VALUES (";
					for (int j = 0; j < 13; j++) 
					{
						sql = sql+"\""+sched[j,i]+"\", ";
					}
					sql = sql+"\""+sched[13,i]+"\");";
					cmd = new MySqlCommand(sql, conn);
					cmd.ExecuteNonQuery();
				}
			} 
			catch (Exception e) 
			{
				if (MessageBox.Show("Unexpected error when writing schedule to database. Would you like to view more detailed information?","Error.",System.Windows.Forms.MessageBoxButtons.YesNo) == System.Windows.Forms.DialogResult.Yes) 
				{
					MessageBox.Show(e.ToString());
				}
				return;
			}
		}


		/*Miscellaneous Helper Functions*/

		//Write the days off from Employee Preferences to the database.
		public void setDaysOff(string[] s, int count) 
		{
			string sql = "DELETE FROM days"+employee.getId()+";";
			cmd = new MySqlCommand(sql, conn);
			try 
			{
				cmd.ExecuteNonQuery();
				for (int i = 0; i < count; i++) 
				{
					sql = "INSERT INTO days"+employee.getId()+" (date) VALUES (\""+s[i]+"\");";
					cmd = new MySqlCommand(sql, conn);
					cmd.ExecuteNonQuery();
				}
			} 
			catch (Exception e) 
			{
				if (MessageBox.Show("An error occurred while setting days off. Would you like to view more detailed information?","Error.",System.Windows.Forms.MessageBoxButtons.YesNo) == System.Windows.Forms.DialogResult.Yes) 
				{
					MessageBox.Show(e.ToString());
				}
				return;
			}
		}


		//Return the MD5 hash of the supplied string.
		public string MD5(string pass) 
		{
			System.Security.Cryptography.MD5CryptoServiceProvider x = new System.Security.Cryptography.MD5CryptoServiceProvider();
			byte[] bs = System.Text.Encoding.UTF8.GetBytes(pass);
			bs = x.ComputeHash(bs);
			System.Text.StringBuilder s = new System.Text.StringBuilder();
			foreach (byte b in bs)
			{
				s.Append(b.ToString("x2").ToLower());
			}
			pass = s.ToString();
			return pass;
		}


		//Delete the manager object created while editting managers from the admin account.
		public void removeTempManager() 
		{
			tempManager = null;
		}


		//Delete the employee object created while editting employees from a manager account.
		public void removeTempEmployee() 
		{
			employee = null;
		}		


		//Create a temporary employee object to allow editting from a manager account.
		public void setTempEmployee(string name) 
		{
			string sql = "SELECT * FROM employees WHERE username=\""+name+"\";";
			cmd = new MySqlCommand(sql, conn);
			MySqlDataReader rdr = cmd.ExecuteReader();
			if (!rdr.Read()) 
			{
				MessageBox.Show("No such employee exists.");
				rdr.Close();
				return;
			}
			//If we get here, the employee does exist.
			Object[] o = new Object[7];
			rdr.GetValues(o);
			employee = new Employee((o[0].ToString()), (o[1].ToString()), (o[2].ToString()), (o[3].ToString()), (o[4].ToString()), (o[5].ToString()), (o[6].ToString()));
			rdr.Close();
		}


		//Create a temporary manager object to allow editting from the admin account.
		public void setTempManager(string name) 
		{
			string sql = "SELECT * FROM managers WHERE username=\""+name+"\";";
			cmd = new MySqlCommand(sql, conn);
			MySqlDataReader rdr = cmd.ExecuteReader();
			if (!rdr.Read()) 
			{
				MessageBox.Show("No such employee exists.");
				rdr.Close();
				return;
			}
			//If we get here, the manager does exist.
			Object[] o = new Object[3];
			rdr.GetValues(o);
			tempManager = new Manager((o[0].ToString()), (o[1].ToString()), (o[2].ToString()));
			rdr.Close();
		}


		/*Schedule Generation Function*/

		//Generate a schedule for a specific week.
		public void generateSchedule(DateTime weekStart)
		{
			//Create an	array of Employee objects containing all employees
			Employee[] employees=getAllEmployees();

			//Convert member variable empsPerShift to an int
			int	employeesPerShift=Convert.ToInt32(empsPerShift);

			//Create a two dimensional string array	to store the schedule
			string[,] schedule=new string[14,employeesPerShift];			
			
			//Create an	array of DateTime objects for the 7	days in	the	week
			DateTime[] week= new DateTime[7];
			for(int	i=0; i<7; i++)
			{
				week[i]=weekStart.AddDays(i);
			}

			//Define some constants
			//lowWeight	is initialized to an abitrarily	high number
			float lowWeight=200;
			int	lowIndex=-1;
			int	avgNumShifts=employeesPerShift*14/employees.Length+1;
	
			//cycle through the 14 shifts in a week
			for(int	i=0; i<14; i++)
			{
				//Determine if each employee is available for the shift and assign them a weight
				for(int k=0; k<employees.Length; k++)
				{
					//If employee has requested this specific day off, mark it as unavailable
					if(employees[k].checkDay(week[i/2]))
						employees[k].setAvailability(i,"0");

					//If employee is available, determine weight
					string availability=employees[k].getAvailability();
					if(availability[i]=='1')
					{
						//current number of	shifts gets	more important as number of	remaining shifts runs out
						//pickiness	is more	important toward the beginning
						//weight is a number between 0 and 1 which grows inversly with pickiness
						//and proportionally with the shiftCount/desiredShiftCount
						float totAvail=employees[k].getTotalAvailability();
						float pickinessFactor=totAvail/14*(13-i);
						float numShifts=employees[k].getShiftCount();
						int desiredShiftCount=avgNumShifts;
						if(employees[k].isPartTime())
							desiredShiftCount/=2;
						float shiftCountFactor=numShifts/desiredShiftCount*i;
						float weight=10*(pickinessFactor+shiftCountFactor)/13;
						
						//Read in preferences
						string amOrPm=employees[k].getTimes();
						string sOrD=employees[k].getShifts();

						//if you like AM(PM) and it's AM(PM) decrease weight
						if((amOrPm=="0"	&& (i%2)==0)||(amOrPm=="1" && (i%2)==1))						
						{
							weight-=1.5F;
							if(weight<0)
								weight=0;
						}
						//if you like AM(PM) and it's PM(AM) increase weight
						else if((amOrPm=="0" &&	(i%2)==1)||(amOrPm=="1"	&& (i%2)==0))
						{
							weight+=1;
						}
						//if you like singles and it's PM
						if(sOrD=="0" &&	i%2==1)
						{
							//if you worked AM increase weight, if not decrease weight
							if(employees[k].isWorking(schedule,i-1,employeesPerShift))
								weight+=1;
							else
								weight-=1;
						}
						//if you like doubles and it's PM
						else if(sOrD=="1" && i%2==1)
						{
							//if you worked AM decrease weight, if not increase weight
							if(employees[k].isWorking(schedule,i-1,employeesPerShift))
								weight-=1.5F;
							else
								weight+=1.5F;
						}
						employees[k].setWeight(weight);
					}
				}
				//Find the employee with the minimum weight for each slot in the shift
				for(int	j=0; j<employeesPerShift; j++)
				{
					for(int k=0; k<employees.GetLength(0); k++)
					{
							if(employees[k].getAvailability()[i]=='1' && employees[k].getWeight()<lowWeight)
							{
								lowWeight=employees[k].getWeight();
								lowIndex=k;
							}
					}
					//This means no employee was available for the slot
					if(lowIndex==-1)
					{
						string[] shifts = {"Sunday AM","Sunday PM","Monday AM","Monday PM","Tuesday AM",
											  "Tuesday PM","Wednesday AM","Wednesday PM","Thursday AM",
											  "Thursday PM","Friday AM","Friday PM","Saturday AM","Saturday PM"};
						MessageBox.Show("Not enough employees available for the " + shifts[i] + " shift.");
						return;
					}
					//Fill in the schedule entry
					schedule[i,j]=employees[lowIndex].getName();

					//increment employees shiftCount and mark this shift unavailable
					employees[lowIndex].incShiftCount();
					employees[lowIndex].setAvailability(i,"0");

					//reset lowWeight and lowIndex
					lowWeight=200;
					lowIndex=-1;
				}
			}
			//write the schedule to the database
			writeSchedule(schedule);
		}
	}
}
